package com.binary.aop;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import com.alibaba.fastjson.JSON;
import com.binary.common.Message;
import com.binary.common.SingleResponseModel;
import com.binary.enums.SuccessOrFailEnum;
import com.binary.exception.BusinessException;
import com.binary.vo.BaseVo;
public class BaseExceptionHander extends SimpleMappingExceptionResolver {
	private static final Logger logger = LoggerFactory.getLogger(BaseExceptionHander.class);

	@Override
	protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
			Exception ex) {
		logger.error(ex.getMessage(), ex);
		//1.省略截取相应的错误信息记入数据库
		//2.异常给前段友好处理
		ResponseBody body = null;
		if (handler instanceof HandlerMethod) {
			HandlerMethod hander = (HandlerMethod) handler;
			body = hander.getMethodAnnotation(ResponseBody.class);
		}
		boolean isNotAjaxRequest = "".equals(request.getHeader("X-Requested-With"))||	
				request.getHeader("X-Requested-With")==null;
		ModelAndView view = new ModelAndView();
		if (body == null&&isNotAjaxRequest) {// href method
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("errorMessage", getErrorMessage(ex));
			map.put("e",deepestException(ex));
			view = new ModelAndView("error", map);
			return view;
		}
		// ajax method
		@SuppressWarnings("rawtypes")
		SingleResponseModel model = new SingleResponseModel();
		Message message = new Message();
		String code = "";
		String msg = "";
		if (ex instanceof BusinessException) {
			code = ((BusinessException) ex).getFriendlyCode() + "";
			msg = ((BusinessException) ex).getFriendlyMsg();

		} else {
			code = "fail";
			msg = ex.getMessage();
		}
		message.setCode(code);
		message.setMessage(msg);
		model.setMessage(message);
		response.reset();
		response.setContentType("text/json;charset=utf-8");
		response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
		response.setHeader("Cache-Control", "no-cache,must-revalidate");
		PrintWriter pw = null;
		try {
			pw = response.getWriter();
			pw.write(JSON.toJSONString(model));
			pw.flush();
		} catch (Exception e) {
			logger.error("统一前端异常操作异常！");
		} finally {
			if (pw != null) {
				pw.close();
			}
		}

		return view;
	}

	/*
	 * @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	 * 
	 * @ExceptionHandler(BusinessException.class)
	 */
	public ModelAndView exceptionHander(HttpServletRequest request, HttpServletResponse response, BusinessException e) {

		logger.error(e.getFriendlyCode() + "》" + e.getFriendlyMsg());
		Object obj = request.getHeader("X-Requested-With");
		ModelAndView view = null;
		SingleResponseModel<BaseVo> model = new SingleResponseModel<BaseVo>();
		if (obj == null || "".equals(obj.toString()) || "null".equals(obj.toString())) {
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("errorMessage", getErrorMessage(e));
			map.put("e", deepestException(e));
			view = new ModelAndView("error", map);

			return view;

		} else {
			view = new ModelAndView();
			PrintWriter pw = null;
			try {
				response.reset();
				response.setContentType("application/json;charset=utf-8");
				pw = response.getWriter();
				Message message = new Message();
				message.setCode(SuccessOrFailEnum.FAIL.getCode());
				message.setMessage(e.getFriendlyMsg());
				model.setMessage(message);
				pw.write(JSON.toJSONString(model));
				pw.flush();
			} catch (Exception e1) {
				logger.error(e1.getMessage(), e1);
			} finally {
				if (pw != null) {
					pw.close();
				}
			}
			return view;

		}

	}

	private String getErrorMessage(Exception e) {
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw);
		e.printStackTrace(pw);
		return sw.toString();
	}

	private Throwable deepestException(Throwable e) {
		Throwable tmp = e;
		int breakPoint = 0;
		while (tmp.getCause() != null) {
			if (tmp.equals(tmp.getCause())) {
				break;
			}
			tmp = tmp.getCause();
			breakPoint++;
			if (breakPoint > 1000) {
				break;
			}
		}
		return tmp;
	}
}
